﻿namespace Arms.Framework.Objects.Geometry
{
    using System;
    using System.Globalization;
    using System.Text;

    [Serializable]
    public class Coordinate : IEquatable<Coordinate>
    {
        private double _x;
        private double _y;

        /// <summary>
        /// Create a new coordinate instance with the given x and y coordinates.
        /// </summary>
        /// <param name="y"></param>
        /// <param name="x"></param>
        public Coordinate(decimal x,decimal y)
        {
            _x = x.ToDouble();
            _y = y.ToDouble();
        }
        /// <summary>
        /// Create a new coordinate instance with the given x and y coordinates.
        /// </summary>
        /// <param name="y"></param>
        /// <param name="x"></param>
        public Coordinate( double x,double y)
        {
            this._x = x;
            this._y = y;
        }
        /// <summary>
        /// Create a new coordinate instance with the given x and y coordinates.
        /// </summary>
        /// <param name="y"></param>
        /// <param name="x"></param>
        public Coordinate( float x,float y)
        {
            this._x = x.ToDouble();
            this._y = y.ToDouble();
        }
        /// <summary>
        /// Gets or sets the x coordinate
        /// </summary>
        public double X
        {
            get { return _x; }
        }
        /// <summary>
        /// Gets or sets the y coordinate
        /// </summary>
        public double Y
        {
            get { return _y; }
        }
        /// <summary>
        /// Gets the string representation of the x and y coordinates.  
        /// Default format is "N6" for 6 decimal precision.
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return this.ToString("N6");
        }
        /// <summary>
        /// Gets the string representation of the x and y coordinates.  
        /// The format is applies to a System.Double, so any format applicable for System.Double will work.
        /// </summary>
        /// <param name="format"></param>
        /// <returns></returns>
        public string ToString(string format)
        {
            StringBuilder sb = new StringBuilder(); //default to 50 in the internal array.
            sb.Append(this.Y.ToString());
            sb.Append(",");
            sb.Append(this.X.ToString());

            return sb.ToString();
        }
        #region Parse

        /// <summary>
        /// Parses a coordinate from a set of x/y string values
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Coordinate Parse(string value)
        {
            if (value == null)
            {
                throw new ApplicationException("value");
            }

            try
            {
                string[] parts = value.Split(',');

                if (parts.Length != 2)
                {
                    throw new FormatException("Missing data for points.");
                }

                double y = parts[0].Trim().ToDouble();
                double x = parts[1].Trim().ToDouble();

                Coordinate coordinate = new Coordinate(x, y);

                return coordinate;
            }
            catch (Exception ex)
            {
                throw new FormatException("Failed to parse coordinate.", ex);
            }
        }

        #endregion

        #region Overrides

        public override bool Equals(object obj)
        {
            return Equals(obj as Coordinate);
        }
        public bool Equals(Coordinate other)
        {
            if (other == null) return false;

            if (other.X == this.X && other.Y == this.Y)
            {
                return true;
            }

            //else
            return false;
        }
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
        #endregion
    }
}
